package com.biboheart.adapter.compiler.utils;

import com.biboheart.adapter.compiler.enums.CharType;
import com.biboheart.adapter.compiler.enums.NodeType;
import com.biboheart.adapter.compiler.enums.TokenLevel;
import com.biboheart.adapter.compiler.enums.TokenType;
import com.biboheart.adapter.compiler.token.Token;
import com.biboheart.adapter.compiler.token.TokenGroup;
import com.biboheart.adapter.support.enums.DelimitEnum;
import com.biboheart.adapter.support.enums.InstructEnum;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class TokenUtils {
    public static char getNext(String content, int offset) {
        if (offset >= content.length() - 1) {
            return '\0';
        } else {
            return content.charAt(offset + 1);
        }
    }

    public static CharType getCharType(char ch) {
        CharType charType;
        if (ch == 0) {
            charType = CharType.CHAR_EOF;
        } else if (ch == 32) { // 空格
            charType = CharType.CHAR_SPACE;
        } else if (ch == '.') {
            charType = CharType.CHAR_DOT;
        } else if ((ch > 64 && ch < 91) || (ch > 96 && ch < 123)) {
            charType = CharType.CHAR_LETTER;
        } else if (ch >= 48 && ch <= 57) {
            charType = CharType.CHAR_NUMBER;
        } else if (ch == 34) {
            charType = CharType.CHAR_DQUOTES;
        } else if (ch == 39) {
            charType = CharType.CHAR_SQUOTES;
        } else if (ch == 95) {
            charType = CharType.CHAR_UNDERLINE;
        } else if (ch == 96) {
            charType = CharType.CHAR_BACKQUOTE;
        } else if (ch >= 33 && ch <= 47 || ch >= 58 && ch <= 64 || ch >= 91 && ch < 96 || ch >= 123 && ch <= 126) {
            charType = CharType.CHAR_CHARACTER;
        } else {
            charType = CharType.CHAR_OTHER;
        }
        return charType;
    }

    // token分组
    public static List<TokenGroup> groupToken(List<Token> tokenList) {
        if (null == tokenList || tokenList.isEmpty()) {
            return null;
        }
        Stack<Token> stack = new Stack<>();
        Stack<Token> caseStack = new Stack<>();
        List<TokenGroup> tokenGroupList = new ArrayList<>();
        List<Token> itemList = new ArrayList<>();
        String type = null;
        if (InstructEnum.INSTRUCT_WHEN.code().equals(tokenList.get(0).getCode()) || InstructEnum.INSTRUCT_ELSE.code().equals(tokenList.get(0).getCode())) {
            TokenLevel tokenLevel = TokenLevel.getLevel(type);
            int level = null == tokenLevel ? 15 : tokenLevel.desc();
            TokenGroup tokenGroup = new TokenGroup(type, level, tokenList);
            tokenGroupList.add(tokenGroup);
            return tokenGroupList;
        }
        for (Token token : tokenList) {
            if (!stack.isEmpty()) {
                itemList.add(token);
                if (DelimitEnum.DELIMIT_SRP.code().equals(token.getCode())) {
                    stack.pop();
                } else if (DelimitEnum.DELIMIT_SLP.code().equals(token.getCode())) {
                    stack.push(token);
                }
            } else if (!caseStack.isEmpty()) {
                itemList.add(token);
                if (InstructEnum.INSTRUCT_END.code().equals(token.getCode())) {
                    caseStack.pop();
                } else if (InstructEnum.INSTRUCT_CASE.code().equals(token.getCode())) {
                    caseStack.push(token);
                }
            } else {
                itemList = new ArrayList<>();
                if (DelimitEnum.DELIMIT_SLP.code().equals(token.getCode())) {
                    type = "(";
                    itemList.add(token);
                    stack.push(token);
                } else if (InstructEnum.INSTRUCT_CASE.code().equals(token.getCode())) {
                    type = "keyword";
                    itemList.add(token);
                    caseStack.push(token);
                } else if (TokenType.TOKEN_KEYWORD.equals(token.getType())) {
                    type = "keyword";
                    itemList.add(token);
                } else if (TokenType.TOKEN_CONSTANT.equals(token.getType())
                        || TokenType.TOKEN_VARIABLE.equals(token.getType())
                        || TokenType.TOKEN_STRING.equals(token.getType())
                        || TokenType.TOKEN_NUMBER.equals(token.getType())
                        || TokenType.TOKEN_NULL.equals(token.getType())){
                    type = "tag";
                    itemList.add(token);
                } else if (TokenType.TOKEN_OPERATOR.equals(token.getType()) || TokenType.TOKEN_LOGICAL.equals(token.getType())) {
                    type = token.getCode();
                    itemList.add(token);
                }
                TokenLevel tokenLevel = TokenLevel.getLevel(type);
                int level = null == tokenLevel ? 15 : tokenLevel.desc();
                TokenGroup tokenGroup = new TokenGroup(type, level, itemList);
                tokenGroupList.add(tokenGroup);
            }
        }
        return tokenGroupList;
    }

    // 取最低优先级的组
    public static Token getLowestLevelToken(List<Token> tokenList) {
        if (null == tokenList || tokenList.isEmpty()) {
            return null;
        }
        List<TokenGroup> tokenGroupList = groupToken(tokenList);
        TokenGroup group = null;
        int level = 0;
        for (TokenGroup tokenGroup : tokenGroupList) {
            if (tokenGroup.getLevel() >= level) {
                // 值越大优先级越低
                level = tokenGroup.getLevel();
                group = tokenGroup;
            }
        }
        if (null == group) {
            return null;
        }
        List<Token> groupTokenList = group.getTokenList();
        return groupTokenList.get(0);
    }

    // 取最优先级的下标
    public static int getLowestLevelIndex(List<TokenGroup> tokenGroupList) {
        if (null == tokenGroupList || tokenGroupList.isEmpty()) {
            return -1;
        }
        int index = 0;
        int level = 0;
        for (int i = 0; i < tokenGroupList.size(); i ++) {
            TokenGroup tokenGroup = tokenGroupList.get(i);
            if (tokenGroup.getLevel() >= level) {
                // 值越大优先级越低
                level = tokenGroup.getLevel();
                index = i;
            }
        }
        return index;
    }

    // 测算节点类型
    public static NodeType compareNodeType(List<Token> tokenList) {
        if (null == tokenList || tokenList.isEmpty()) {
            return null;
        }
        List<TokenGroup> tokenGroupList = groupToken(tokenList);
        int index = getLowestLevelIndex(tokenGroupList);
        TokenGroup tokenGroup = tokenGroupList.get(index);
        List<Token> list = tokenGroup.getTokenList();
        if (list.size() > 1) {
            // 最低优先级大于1说明是括号级, 查看前面是不是指令
            tokenList.remove(0);
            Token last = tokenList.get(tokenList.size() - 1);
            if (DelimitEnum.DELIMIT_SRP.code().equals(last.getCode())) {
                tokenList.remove(tokenList.size() - 1);
            }
            return compareNodeType(tokenList);
        }
        return compareNodeType(list.get(0));
    }

    // 测算节点类型
    public static NodeType compareNodeType(Token token) {
        if (null == token) {
            return null;
        }
        NodeType nodeType = null;
        if (TokenType.TOKEN_KEYWORD.equals(token.getType())) {
            nodeType = NodeType.NODE_COMMAND;
        } else if (TokenType.TOKEN_VARIABLE.equals(token.getType())) {
            nodeType = NodeType.NODE_VARIABLE;
        } else if (TokenType.TOKEN_CONSTANT.equals(token.getType())
                || TokenType.TOKEN_STRING.equals(token.getType())
                || TokenType.TOKEN_NUMBER.equals(token.getType())
                || TokenType.TOKEN_NULL.equals(token.getType())) {
            nodeType = NodeType.NODE_CONSTANT;
        } else if (TokenType.TOKEN_LOGICAL.equals(token.getType()) || TokenType.TOKEN_OPERATOR.equals(token.getType())) {
            nodeType = NodeType.NODE_OPERATOR;
        }
        return nodeType;
    }
}
